﻿using System;
using System.Drawing;
using System.Linq;
using System.Threading;
using System.Windows.Forms;
using AMM.CustomClassLibrary;

namespace AMM.Forms {
    public partial class FrmRootBase : Form {

        protected static string LoginUserName = "System";
        protected static int LoginUserId = 1;
        protected static bool IsOffline = false;
        protected static bool IsSystem = false;

        protected override void WndProc(ref Message m) {
            if (m.Msg == NativeMethods.WM_SHOWME) {
                if (WindowState == FormWindowState.Minimized) {
                    WindowState = FormWindowState.Maximized;
                }
                // get our current "TopMost" value (ours will always be false though)
                bool top = this.TopMost;
                // make our form jump to the top of everything
                this.TopMost = true;
                // set it back to whatever it was
                this.TopMost = top;
            }
            base.WndProc(ref m);
        }

        public override string Text {
            get {
                if (!string.IsNullOrEmpty(base.Text) && base.Text.Contains('-')) {
                    return base.Text.Split('-')[1].Trim();
                }
                else {
                    return string.Empty;
                }
            }
            set {
                base.Text = string.Format("AMM - {0}", value);
            }
        }

        public FrmRootBase() { this.InitializeComponent(); }

        #region Private members

        private void FrmRootBase_Load(object sender, EventArgs e) {
            /*
             * Notice: We must promise that we never execute any long time processing in DesignMode * 
            */
            this.transparencyLabelExLoading.BringToFront();
            this.transparencyLabelExLoading.Location = new Point(0, 0);
            this.transparencyLabelExLoading.Width = this.Width;
            this.transparencyLabelExLoading.Height = this.Height;
            this.transparencyLabelExLoading.TextAlignment = ContentAlignment.MiddleCenter;
            this.pbProcessing.BringToFront();
            this.pbProcessing.Location = new Point((this.Width - this.pbProcessing.Width) / 2, (this.Height - this.pbProcessing.Height) / 2);

            this.ExitApplicaton = false;
            this.PreventCancel = false;

            if (this.DesignMode) {
                this.transparencyLabelExLoading.Visible = this.pbProcessing.Visible = false;
            }
        }

        private void FrmRootBase_Resize(object sender, EventArgs e) {
            this.pbProcessing.Location = new Point((this.Width - this.pbProcessing.Width) / 2, (this.Height - this.pbProcessing.Height) / 2);
            this.Invalidate();
        }

        private void FrmRootBase_FormClosing(object sender, FormClosingEventArgs e) {
            e.Cancel = this.PreventCancel;
        }

        private void FrmRootBase_FormClosed(object sender, FormClosedEventArgs e) {
            if (this.ExitApplicaton) {
                ((Form)sender).Dispose();
                Application.Exit();
            }
        }

        #endregion

        #region Protected members

        protected delegate void ThreadDelegate();
        protected delegate void ThreadDelegate<T>(T param1);
        protected delegate void ThreadDelegate<T, T1>(T param1, T1 param2);

        #region Properties

        protected bool ExitApplicaton { get; set; }
        protected bool PreventCancel { get; set; }
        protected virtual string FunctionCode {
            get { return string.Empty; }
        }

        #endregion

        protected void OperateException(Exception ex) {
            string msg = MethodHelper.ExtractExceptionMessage(ex);
            Logger.Error(msg);
        }

        protected DialogResult ShowError(string message) {
            return MessageBox.Show(message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
        }

        protected DialogResult ShowInfo(string message) {
            return MessageBox.Show(message, "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
        }

        protected DialogResult ShowQuestion(string message) {
            return MessageBox.Show(message, "提示", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2);
        }

        protected virtual void Button_Click(object sender, EventArgs e) { }

        #region Thread

        /// <summary>
        /// Create a new thread.
        /// </summary>
        /// <param name="action">The thread delegate will run code, 
        /// if you want to use process bar, you should override the UpdateProcessBar method. 
        /// you must invoke the UpdateProcessBar method in the thread delegate running code.</param>
        /// <param name="action1">As soon as the thread finished, the Action will run, you can update UI elements in this method</param>
        protected void CreateNewThread(Action action, Action action1 = null) {
            this.transparencyLabelExLoading.Visible = this.pbProcessing.Visible = true;
            Thread t = new Thread(new ThreadStart(() => {
                try {
                    action.Invoke();
                }
                catch (Exception ex) {
                    this.OperateException(ex);
                    this.ShowError(ex.Message);
                }
                finally {
                    if (action1 != null) {
                        this.UpdateUIElements(action1);
                    }
                }
            }));
            t.IsBackground = true;
            t.Start();
        }

        private void UpdateUIElements(Action action) {
            while (!this.IsHandleCreated) { this.CreateHandle(); }
            if (this.InvokeRequired) {
                this.Invoke(new ThreadDelegate<Action>(UpdateUIElements), action);
            }
            else {
                action.Invoke();
                this.transparencyLabelExLoading.Visible = this.pbProcessing.Visible = false;
            }
        }

        protected virtual void UpdateProcessBar(int value, int totalValue) { }
        /*
        Example: How to implement UpdateProcessBar Method.
        protected override void UpdateProcessBar(int value) {
            if (this.InvokeRequired) {
                this.Invoke(new ThreadDelegate<int>(UpdateProcessBar), value);
            }
            else {
                this.proStatus.Visible = true;
                this.proStatus.Value = value * 20;
            }
        }
        */

        protected void CreateNewThreadNoProcessIcon(Action action, Action action1 = null) {
            Thread t = new Thread(new ThreadStart(() => {
                try {
                    action.Invoke();
                }
                catch (Exception ex) {
                    this.OperateException(ex);
                    this.ShowError(ex.Message);
                }
                finally {
                    if (action1 != null) {
                        this.UpdateUIElementsNoProcessIcon(action1);
                    }
                }
            }));
            t.IsBackground = true;
            t.Start();
        }

        private void UpdateUIElementsNoProcessIcon(Action action) {
            while (!this.IsHandleCreated) { this.CreateHandle(); }
            if (this.InvokeRequired) {
                this.Invoke(new ThreadDelegate<Action>(UpdateUIElementsNoProcessIcon), action);
            }
            else {
                action.Invoke();
            }
        }

        #endregion

        #endregion
    }
}
